Day 2 我們成功從 A repo trigger B repo,但我們的目的是為了讓 B repo 可以因為 merge request 被觸發後,拿著這個merge request 的 event 來做 ai code review。所以我們現在要來看 A 的 payload 如何讓 B 拿到。
這段其實在 A repo trigger webhook 的時候就會帶進去了,所以難度沒有很高,我們來看一下官網,我們在 B repo(被 trigger 的) gitlab ci 內加上 cat payload
cat $TRIGGER_PAYLOAD
commit 後在 A repo 再 test 一次 webhook,就可以拿到以下資料,而其中最重要的就是我們在 Day 1 自己手動帶入的 merge request url。在這邊則是 object_attributes[“url“]
$ cat $TRIGGER_PAYLOAD
{
"object_kind":"merge_request",
"event_type":"merge_request",
"user":{
"id":12081700,
"name":"Alvin",
"username":"ooii8929",
...
},
"project":{
"id":60505829,
"name":"main-feature",
"description":null,
...
},
"object_attributes":{
"url":"https://gitlab.com/ooii8929/main-feature/-/merge_requests/2",
...
},
"labels":[
...
],
"changes":{
},
"repository":{
...
}
根據官網介紹,TRIGGER_PAYLOAD 是 file type 的變數(指向包含 JSON 數據的臨時文件的路徑),所以我們使用 jq -r 來讓 jq 向路徑上的文件進行讀取
- URL=$(jq -r '.object_attributes.url' $TRIGGER_PAYLOAD)
- echo $URL
為了使用 jq,我們也拉一個乾淨的 image 來進行安裝
build_job:
stage: build
image: alpine:latest
before_script:
- apk add --no-cache jq
script:
- cat $TRIGGER_PAYLOAD
- URL=$(jq -r '.object_attributes.url' $TRIGGER_PAYLOAD)
- echo $URL
為了達到我們原本在 local 可以用 python 運行的方式,我們想像會執行以下動作
python3 -m pr_agent.cli --pr_url $URL review
所以我會拆出另一個 stage,使用 python image,並且用 artifacts 在不同 stage 之間共享 $URL
stages:
- pre-set
- run
build_job:
stage: pre-set
image: alpine:latest
before_script:
- apk add --no-cache jq
script:
- cat $TRIGGER_PAYLOAD
- URL=$(jq -r '.object_attributes.url' $TRIGGER_PAYLOAD)
- echo "URL=$URL" > build.env
- cat build.env
artifacts:
reports:
dotenv: build.env
run_code:
stage: run
image: python:3-alpine
script:
- echo $URL
# - python3 -m pr_agent.cli --pr_url $URL review
一樣回到 main-feature webhook 測試,確認在 run stage 有 echo 出來 URL
再來我們要將程式推上 git,因為程式內會填入兩個 sensitive info(OpenAI key & personal access token),所以我們會善用 gitlab cicd variables 來做資安保護。
先來到 ai-review-runner 的 settings → cicd → Variables ,建立兩個 Variables: OPEN_AI_TOKEN 跟 PERSONAL_ACCESS_TOKEN ,並且各別設置 MASK
好了之後,我們前往原本設定的 pr-agent 的 .secret.toml 設定成變數
[openai]
key = "$OPEN_AI_TOKEN"
[gitlab]
# Gitlab personal access token
personal_access_token = "$PERSONAL_ACCESS_TOKEN"
然後在 .gitignore 我們將 pr_agent/settings/.secrets.toml 給註解掉。不然推的時候會少這個 file。然後我們在 ai-review-runner 建立一個 pr-agent folder 將 pr_agent 整個檔案都放進去。
# 放之前
tree -L 1 -a
.
├── .git
├── .gitlab-ci.yml
└── README.md
# 放之後
tree -L 2 -a
.
├── .git
│ ├── COMMIT_EDITMSG
│ ├── FETCH_HEAD
│ ├── HEAD
│ ├── ORIG_HEAD
│ ├── config
│ ├── description
│ ├── gc.log
│ ├── hooks
│ ├── index
│ ├── info
│ ├── logs
│ ├── objects
│ ├── packed-refs
│ └── refs
├── .gitignore
├── .gitlab-ci.yml
├── README.md
└── pr-agent
├── .dockerignore
├── .gitignore
├── .pr_agent.toml
├── CHANGELOG.md
├── Dockerfile.github_action
├── Dockerfile.github_action_dockerhub
├── LICENSE
├── MANIFEST.in
├── README.md
├── RELEASE_NOTES.md
├── action.yaml
├── docker
├── docs
├── github_action
├── pr_agent
├── pr_agent.egg-info
├── pyproject.toml
├── requirements-dev.txt
├── requirements.txt
├── setup.py
└── tests
推上 gitlab 並且在 .gitlab-ci.yml 使用 python
run_code:
stage: run
image: python:3-alpine
script:
- echo $URL
- cd pr-agent
- python3 -m pr_agent.cli --pr_url $URL review
然後再來測試一次。但我們會發現它會遇到 get git provider 錯誤問題,看樣子是 personal access token 沒有權限,但我們之前在 Local 用同一把是成功的,所以應該是設定沒設定好
File "/builds/ooii8929/ai-review-runner/pr-agent/pr_agent/git_providers/__init__.py", line 62, in get_git_provider_with_context
raise ValueError(f"Failed to get git provider for {pr_url}") from e
ValueError: Failed to get git provider for https://gitlab.com/ooii8929/main-feature/-/merge_requests/2
我們在 gitlab provider 新增 print 看看我們的參數有沒有正常帶進去。會發現它會印出
class GitLabProvider(GitProvider):
def __init__(self, merge_request_url: Optional[str] = None, incremental: Optional[bool] = False):
gitlab_url = get_settings().get("GITLAB.URL", None)
if not gitlab_url:
raise ValueError("GitLab URL is not set in the config file")
print("for test", get_settings().get("GITLAB.PERSONAL_ACCESS_TOKEN", None))
gitlab_access_token = get_settings().get("GITLAB.PERSONAL_ACCESS_TOKEN", None)
for test ${PERSONAL_ACCESS_KEY}
代表沒有真的完成變數帶入
這邊也額外補充一下,我們改成讓他每次 trigger 才會觸發
rules:
- if: $CI_PIPELINE_SOURCE == "trigger"